/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.controller.func;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.ConstantVars;
import com.je.common.base.constants.table.TableType;
import com.je.common.base.db.JEDatabase;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.mvc.AbstractPlatformController;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.result.BaseRespResult;
import com.je.common.base.service.MetaRbacService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.service.rpc.SystemSettingRpcService;
import com.je.common.base.util.ArrayUtils;
import com.je.common.base.util.StringUtil;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.ibatis.extension.plugins.pagination.Page;
import com.je.meta.service.func.MetaFuncRelationService;
import com.je.rbac.rpc.PermissionRpcService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 字段导入配置
 */
@RestController
@RequestMapping(value = "/je/meta/funRelation")
public class FunRelationController extends AbstractPlatformController {

    @Autowired
    private MetaRbacService metaRbacService;
    @Autowired
    private MetaFuncRelationService metaFuncRelationService;
    @Autowired
    private SystemSettingRpcService systemSettingRpcService;
    @Autowired
    private PermissionRpcService permissionRpcService;

    /**
     * 获取功能下的子功能集合
     *
     * @param param
     * @param request
     * @return
     */
    @RequestMapping(value = "/getChildList", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getChildList(BaseMethodArgument param, HttpServletRequest request) {
        String funcId = param.getFuncId();
        Page page = new Page<>(param.getPage(), param.getLimit());
        List<Map<String, Object>> list = metaFuncRelationService.getChildList(page, funcId);
        page.setRecords(list);
        return BaseRespResult.successResultPage(page.getRecords(), (long) list.size());
    }

    /**
     * 获取当前功能的父功能和子功能
     */
    @RequestMapping(value = "/getParentAndChildInfo", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult getParentAndChildInfo(BaseMethodArgument param, HttpServletRequest request) {
        String funcId = param.getFuncId();
        Map<String,Object> map = metaFuncRelationService.getParentAndChildInfo(funcId);
        return BaseRespResult.successResult(map);
    }


    /**
     * @param param
     */
    @RequestMapping(value = "/doSave", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @Override
    public BaseRespResult doSave(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        dynaBean.setStr("FUNCRELATION_ENABLED", "1");
        dynaBean.setStr("SY_ORDERINDEX", "0");
        dynaBean.setStr("FUNCRELATION_SHOWTYPE", StringUtil.getDefaultValue(systemSettingRpcService.findSettingValue("FUNCINFO_CHILDSHOWTYPE"), "formOuterHorizontal"));
        String codeGenFieldInfo = param.getCodeGenFieldInfo();
        String funcCode = param.getFuncCode();
        //构建创新基础信息
        commonService.buildModelCreateInfo(dynaBean);
        String funcChildCode = dynaBean.getStr("FUNCRELATION_CODE");
        String error = "";
        List<DynaBean> funcChilds = metaService.select("JE_CORE_FUNCRELATION",
                ConditionsWrapper.builder().eq("FUNCRELATION_CODE", funcChildCode));
        if (funcChilds.size() > 0) {
            DynaBean mainFunc = metaService.selectOneByPk("JE_CORE_FUNCINFO", funcChilds.get(0).getStr("FUNCRELATION_FUNCINFO_ID"));
            error = "子功能编码【" + funcChildCode + "】已在功能【" + mainFunc.getStr("FUNCINFO_FUNCNAME") + "】中是子功能，无法重复添加!";
        }
        if (StringUtil.isNotEmpty(error)) {
            return BaseRespResult.errorResult(error);
        }

        List<DynaBean> menus = metaRbacService.selectByTableCodeAndNativeQuery("JE_CORE_MENU", NativeQuery.build().eq("MENU_NODEINFO", funcChildCode).eq("MENU_NODEINFOTYPE", "MT"));
        if (menus != null && menus.size() > 0) {
            error = "功能【" + funcChildCode + "】已在菜单【" + menus.get(0).getStr("MENU_MENUNAME") + "】中引用，无法重复添加!";
        }
        if (StringUtil.isNotEmpty(error)) {
            return BaseRespResult.errorResult(error);
        }
        //构建编号
        if (StringUtil.isNotEmpty(codeGenFieldInfo)) {
            commonService.buildCode(codeGenFieldInfo, dynaBean);
        }
        //保存数据
        DynaBean inserted = commonService.doSave(dynaBean);
        if (ArrayUtils.contains(new String[]{"func", "tree", "view", "childfuncfield", "procedure", "iditprocedure", "sql"}, inserted.getStr("SY_STATUS"))) {
            doChildByTable(inserted);
        }
        //检测子功能是否增加ROOT节点
        commonService.doChildrenTree(inserted, funcCode);
        //返回给前台
        commonService.buildModelCreateInfo(dynaBean);
        return BaseRespResult.successResult(inserted);
    }

    /**
     * TODO未处理
     *
     * @param param
     */
    @RequestMapping(value = "/doUpdateList", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @Override
    public BaseRespResult doUpdateList(BaseMethodArgument param, HttpServletRequest request) {
        String strData = param.getStrData();
        String funcId = param.getFuncId();
        DynaBean funcInfoBean = metaService.selectOneByPk("JE_CORE_FUNCINFO", funcId);

        //-----------开始，找到变更的子功能,并修改其权限编码为最新的权限编码-----------
        JSONArray strJsonArr = JSON.parseArray(strData);
        List<String> codeIdList = new ArrayList<>();
        for (int i = 0; i < strJsonArr.size(); i++) {
            if (strJsonArr.getJSONObject(i).containsKey("JE_CORE_FUNCRELATION_ID")
                    && !com.beust.jcommander.Strings.isStringEmpty(strJsonArr.getJSONObject(i).getString("JE_CORE_FUNCRELATION_ID"))) {
                codeIdList.add(strJsonArr.getJSONObject(i).getString("JE_CORE_FUNCRELATION_ID"));
            }
        }

        if (!codeIdList.isEmpty()) {
            List<DynaBean> oldSubFuncBeanList = metaService.select("JE_CORE_FUNCRELATION", ConditionsWrapper.builder().in("JE_CORE_FUNCRELATION_ID", codeIdList));
            for (DynaBean eachSubFuncBean : oldSubFuncBeanList) {
                for (int i = 0; i < strJsonArr.size(); i++) {
                    if (eachSubFuncBean.getStr("JE_CORE_FUNCRELATION_ID").equals(strJsonArr.getJSONObject(i).getString("JE_CORE_FUNCRELATION_ID"))) {
                        if (strJsonArr.getJSONObject(i).containsKey("FUNCRELATION_CODE")
                                && !Strings.isNullOrEmpty(strJsonArr.getJSONObject(i).getString("FUNCRELATION_CODE"))
                                && !eachSubFuncBean.getStr("FUNCRELATION_CODE").equals(strJsonArr.getJSONObject(i).getString("FUNCRELATION_CODE"))) {
                            permissionRpcService.modifySubFuncPermCode(funcInfoBean.getStr("FUNCINFO_FUNCCODE"), eachSubFuncBean.getStr("FUNCRELATION_CODE"), strJsonArr.getJSONObject(i).getString("FUNCRELATION_CODE"));
                        }
                    }
                }
            }
        }
        //-----------结束，找到变更的子功能,并修改其权限编码为最新的权限编码-----------

        String codeGenFieldInfo = param.getCodeGenFieldInfo();
        List<DynaBean> updateList = commonService.doUpdateList("JE_CORE_FUNCRELATION", strData, null, null, codeGenFieldInfo);
        return BaseRespResult.successResult(updateList.size() + "条记录被更新!");
    }

    /**
     * TODO未处理
     *
     * @param param
     */
    @RequestMapping(value = "/insertAny", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult insertAny(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");

        DynaBean funInfo = metaService.selectOne("JE_CORE_FUNCINFO",
                ConditionsWrapper.builder().apply(" and FUNCINFO_FUNCCODE={0}", dynaBean.getStr("FUNCRELATION_CODE")));
        if (funInfo != null) {
            return BaseRespResult.errorResult("功能编码重复");
        }
        manager.doSave(param, request);
        return BaseRespResult.successResult(null, "添加成功");
    }

    /**
     * TODO未处理
     *
     * @param param
     */
    @RequestMapping(value = "/doRemove", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    @Override
    public BaseRespResult doRemove(BaseMethodArgument param, HttpServletRequest request) {
        String ids = param.getIds();
        if (StringUtil.isNotEmpty(ids)) {
            //todo 清除子功能授权
            metaService.executeSql("DELETE FROM JE_CORE_ASSOCIATIONFIELD WHERE ASSOCIATIONFIELD_FUNCRELAT_ID IN ({0})", Arrays.asList(ids.split(",")));
        }
        int delNum = manager.doRemove(param, request);
        return BaseRespResult.successResult(delNum + "条记录被删除!");
    }

    /**
     * 导入按钮   导入当前功能的子功能
     *
     * @author sunwanxiang
     * @date 2012-4-23 上午11:01:25
     */
    @RequestMapping(value = "/doImpl", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult doImpl(BaseMethodArgument param, HttpServletRequest request) {
        String ids = param.getIds();
        if (Strings.isNullOrEmpty(ids)) {
            return BaseRespResult.errorResult("传入信息失败!");
        }
        List<DynaBean> funcInfos = metaService.select("JE_CORE_FUNCINFO",
                ConditionsWrapper.builder().in("JE_CORE_FUNCINFO_ID", ids.split(ArrayUtils.SPLIT)));
        //首先先检测是否可以导入
        String error = "";
        for (DynaBean funcInfo : funcInfos) {
            List<DynaBean> funcChilds = metaService.select("JE_CORE_FUNCRELATION",
                    ConditionsWrapper.builder().eq("FUNCRELATION_CODE", funcInfo.getStr("FUNCINFO_FUNCCODE")));
            if (funcChilds.size() > 0) {
                DynaBean mainFunc = metaService.selectOneByPk("JE_CORE_FUNCINFO", funcChilds.get(0).getStr("FUNCRELATION_FUNCINFO_ID"));
                error = "功能【" + funcInfo.getStr("FUNCINFO_FUNCNAME") + "】已在功能【" + mainFunc.getStr("FUNCINFO_FUNCNAME") + "】中是子功能，无法重复添加!";
                break;
            }
            List<DynaBean> menus = metaRbacService.selectByTableCodeAndNativeQuery("JE_CORE_MENU",
                    NativeQuery.build().applyWithParams(" MENU_NODEINFO={0} AND MENU_NODEINFOTYPE='MT'", funcInfo.getStr("FUNCINFO_FUNCCODE")));
            if (menus.size() > 0) {
                error = "功能【" + funcInfo.getStr("FUNCINFO_FUNCNAME") + "】已在菜单【" + menus.get(0).getStr("MENU_MENUNAME") + "】中引用，无法重复添加!";
                break;
            }
        }
        if (StringUtil.isNotEmpty(error)) {
            return BaseRespResult.errorResult(error);
        }
        DynaBean funcRelation;
        List<DynaBean> returnData = new ArrayList<>();
        for (DynaBean funcInfo : funcInfos) {
            funcRelation = new DynaBean("JE_CORE_FUNCRELATION", false);
            funcRelation.set(BeanService.KEY_PK_CODE, "JE_CORE_FUNCRELATION_ID");
            funcRelation.set("FUNCRELATION_NAME", funcInfo.getStr("FUNCINFO_FUNCNAME"));
            funcRelation.set("FUNCRELATION_CODE", funcInfo.getStr("FUNCINFO_FUNCCODE"));
            funcRelation.set("FUNCRELATION_FUNCID", funcInfo.getStr("JE_CORE_FUNCINFO_ID"));
            funcRelation.set("FUNCRELATION_ENABLED", "1");
            funcRelation.set("FUNCRELATION_COPY", "1");
            funcRelation.set("SY_ORDERINDEX", 0);//默认为0
            funcRelation.set("FUNCRELATION_ENTITYNAME", "");
            funcRelation.set("FUNCRELATION_TABLENAME", funcInfo.getStr("FUNCINFO_TABLENAME"));
            funcRelation.set("FUNCRELATION_FUNCINFO_ID", getStringParameter(request, "FUNCRELATION_FUNCINFO_ID"));
            funcRelation.setStr("FUNCRELATION_SHOWTYPE", StringUtil.getDefaultValue(systemSettingRpcService.findSettingValue("FUNCINFO_CHILDSHOWTYPE"), "formOuterHorizontal"));
            if ("tree".equals(funcInfo.getStr("FUNCINFO_FUNCTYPE"))) {
                funcRelation.set("FUNCRELATION_RELYONTYPE", "tree");
            } else {
                funcRelation.set("FUNCRELATION_RELYONTYPE", "func");
            }
            commonService.buildModelCreateInfo(funcRelation);
            metaService.insert(funcRelation);
            doChildByTable(funcRelation);
            returnData.add(funcRelation);
        }
        return BaseRespResult.successResult(returnData, "导入成功!");
    }

    /**
     * 添加子功能关联关系
     */
    @RequestMapping(value = "/saveRelationSet", method = RequestMethod.POST, produces = "application/json; charset=utf-8")
    public BaseRespResult saveRelationSet(BaseMethodArgument param, HttpServletRequest request) {
        DynaBean dynaBean = (DynaBean) request.getAttribute("dynaBean");
        dynaBean = metaFuncRelationService.saveRelationSet(dynaBean);
        return BaseRespResult.successResult(dynaBean, "导入成功!");
    }

    /**
     * 字段关联
     *
     * @param inserted
     */
    @Transactional
    public void doChildByTable(DynaBean inserted) {
        DynaBean parentFunc = metaService.selectOneByPk("JE_CORE_FUNCINFO", inserted.getStr("FUNCRELATION_FUNCINFO_ID"));
        String parentTableCode = parentFunc.getStr("FUNCINFO_TABLENAME");
        //如果主功能是视图，则取视图的主表作为父表
        DynaBean tableInfo = metaService.selectOne("JE_CORE_RESOURCETABLE",
                ConditionsWrapper.builder().eq("RESOURCETABLE_TABLECODE", parentTableCode));
        //视图主表的主键编码
        String viewMasterTablePkCode = null;
        if (TableType.VIEWTABLE.equals(tableInfo.getStr("RESOURCETABLE_TYPE"))) {
            parentTableCode = getMasterTable(tableInfo);
            viewMasterTablePkCode = tableInfo.getStr("RESOURCETABLE_PKCODE");
        }
        String childTableCode = inserted.getStr("FUNCRELATION_TABLENAME");
        /**
         * 如果发现子功能有外键并且外键是该主功能所依赖的表  则自动生成关联字段
         */
        List<DynaBean> keys = metaService.select("JE_CORE_TABLEKEY",
                ConditionsWrapper.builder().apply("TABLEKEY_TABLECODE={0} AND TABLEKEY_LINKTABLE={1} AND TABLEKEY_TYPE='Foreign' AND TABLEKEY_ISCREATE='1'", childTableCode, parentTableCode));
        String sql = " AND TABLECOLUMN_CHILDCONFIG!='' AND TABLECOLUMN_CHILDCONFIG IS NOT NULL";
        if (ConstantVars.STR_ORACLE.equals(JEDatabase.getCurrentDatabase())
                || ConstantVars.STR_SHENTONG.equals(JEDatabase.getCurrentDatabase())
                || ConstantVars.STR_MYSQL.equals(JEDatabase.getCurrentDatabase())) {
            sql = " AND TABLECOLUMN_CHILDCONFIG IS NOT NULL";
        }
        List<DynaBean> columns = metaService.select("JE_CORE_TABLECOLUMN",
                ConditionsWrapper.builder().apply("TABLECOLUMN_TABLECODE={0} " + sql, childTableCode));
        String foreignKey = "";
        DynaBean assField;
        for (DynaBean key : keys) {
            //如果主功能是视图，则必须用子表的外键编码和主表的主键编码关联
            if (StringUtil.isNotEmpty(viewMasterTablePkCode)
                    && !viewMasterTablePkCode.equals(key.getStr("TABLEKEY_LINECOLUMNCODE"))) {
                continue;
            }
            assField = new DynaBean("JE_CORE_ASSOCIATIONFIELD", false);
            assField.set(BeanService.KEY_PK_CODE, "JE_CORE_ASSOCIATIONFIELD_ID");
            assField.set("ASSOCIATIONFIELD_FUNCRELAT_ID", inserted.getStr("JE_CORE_FUNCRELATION_ID"));
            assField.set("ASSOCIATIONFIELD_FID", inserted.getStr("FUNCRELATION_FUNCINFO_ID"));
            assField.set("ASSOCIATIONFIELD_PID", inserted.getStr("FUNCRELATION_FUNCID"));
            //whereSq
            assField.set("ASSOCIATIONFIELD_WHERECON", "1");
            //传值
            assField.set("ASSOCIATIONFIELD_TRANSMIT", "1");
            //是否硬编码
            assField.set("ASSOCIATIONFIELD_HARD", "0");
            //级联删除
            assField.set("ASSOCIATIONFIELD_DELCHILD", "0");
            //级联更新
            assField.set("ASSOCIATIONFIELD_CASCADEUPDATE", "0");
            //关联关系
            assField.set("ASSOCIATIONFIELD_ASSOCIATION", "=");
            //子功能字段
            assField.set("ASSOCIATIONFIELD_CHIFIELDCODE", key.getStr("TABLEKEY_COLUMNCODE"));
            //关联关系
            assField.set("ASSOCIATIONFIELD_CHIFIELDNAME", "外键");
            //关联关系
            assField.set("ASSOCIATIONFIELD_PRIFIELDCODE", key.getStr("TABLEKEY_LINECOLUMNCODE"));
            foreignKey = key.getStr("TABLEKEY_LINECOLUMNCODE");
            //关联关系
            assField.set("ASSOCIATIONFIELD_PRIFIELDNAME", "主键ID");
            commonService.buildModelCreateInfo(assField);
            metaService.insert(assField);
        }
        for (DynaBean column : columns) {
            String childConfig = column.getStr("TABLECOLUMN_CHILDCONFIG");
            String[] childArray = childConfig.split(ArrayUtils.SPLIT);
            if (childArray.length != 2) {
                continue;
            }
            if (parentTableCode.equals(childArray[0]) && StringUtil.isNotEmpty(childArray[1]) && !foreignKey.equals(childArray[1])) {
                DynaBean parentColumn = metaService.selectOne("JE_CORE_TABLECOLUMN",
                        ConditionsWrapper.builder().apply("TABLECOLUMN_TABLECODE={0} AND TABLECOLUMN_CODE={1}", parentTableCode, childArray[1]));
                assField = new DynaBean("JE_CORE_ASSOCIATIONFIELD", false);
                assField.set(BeanService.KEY_PK_CODE, "JE_CORE_ASSOCIATIONFIELD_ID");
                assField.set("ASSOCIATIONFIELD_FUNCRELAT_ID", inserted.getStr("JE_CORE_FUNCRELATION_ID"));
                assField.set("ASSOCIATIONFIELD_FID", inserted.getStr("FUNCRELATION_FUNCINFO_ID"));
                assField.set("ASSOCIATIONFIELD_PID", inserted.getStr("FUNCRELATION_FUNCID"));
                //whereSq
                assField.set("ASSOCIATIONFIELD_WHERECON", "0");
                //传值
                assField.set("ASSOCIATIONFIELD_TRANSMIT", "1");
                //是否硬编码
                assField.set("ASSOCIATIONFIELD_HARD", "0");
                //级联删除
                assField.set("ASSOCIATIONFIELD_DELCHILD", "0");
                //级联更新
                assField.set("ASSOCIATIONFIELD_CASCADEUPDATE", "0");
                //关联关系
                assField.set("ASSOCIATIONFIELD_ASSOCIATION", "no");
                //子功能字段
                assField.set("ASSOCIATIONFIELD_CHIFIELDCODE", column.getStr("TABLECOLUMN_CODE"));
                //关联关系
                assField.set("ASSOCIATIONFIELD_CHIFIELDNAME", column.getStr("TABLECOLUMN_NAME"));
                //关联关系
                assField.set("ASSOCIATIONFIELD_PRIFIELDCODE", parentColumn.getStr("TABLECOLUMN_CODE"));
                //关联关系
                assField.set("ASSOCIATIONFIELD_PRIFIELDNAME", parentColumn.getStr("TABLECOLUMN_NAME"));
                commonService.buildModelCreateInfo(assField);
                metaService.insert(assField);
            }

        }
    }

    /**
     * 视图的主键为主表的主键
     * 视图的基表必定与视图在同一个服务模块中
     *
     * @param tableInfo
     * @return
     */
    private String getMasterTable(DynaBean tableInfo) {
        String tableCodeId = tableInfo.getStr("JE_CORE_RESOURCETABLE_ID");

        DynaBean pkColumnInfo = metaService.selectOne("JE_CORE_TABLECOLUMN",
                ConditionsWrapper.builder().eq("TABLECOLUMN_RESOURCETABLE_ID", tableCodeId)
                        .eq("TABLECOLUMN_TYPE", "ID"));

        if (pkColumnInfo == null || StringUtil.isEmpty(pkColumnInfo.getStr("TABLECOLUMN_VIEWCONFIG"))) {
            return null;
        }
        JSONObject jsonObject = JSON.parseObject(pkColumnInfo.getStr("TABLECOLUMN_VIEWCONFIG"));
        //由于视图的基表也可能是视图，所以需判断主表是否是视图，如果是则返回null
        String masterTableCode = jsonObject.getString("tableCode");
        DynaBean masterTable = metaService.selectOne("JE_CORE_RESOURCETABLE", ConditionsWrapper.builder().eq("RESOURCETABLE_TABLECODE", masterTableCode));
        if (TableType.VIEWTABLE.equals(masterTable.getStr("RESOURCETABLE_TYPE"))) {
            return null;
        }
        return masterTableCode;
    }
}
